package toolib.geom;

import java.util.ArrayList;
import java.util.Iterator;

public class V2fList extends ArrayList<V2f> {
	
	private static final long serialVersionUID = 1L;

	public V2fList () {
		super ();
	}
	
	public final V2f hasVector (float theX, float theY) {
		Iterator<V2f> it = iterator ();
		V2f v;
		while (it.hasNext ()) {
			v = it.next ();
			if (v.equals (theX, theY)) {
				return v;
			}
		}
		return null;
	}
	
	public final V2f hasVector (V2f theVector) {
		return hasVector (theVector.x, theVector.y);
	}
	
	public final V2f hasVector (float theX, float theY, float theTolerance) {
		Iterator<V2f> it = iterator ();
		V2f v;
		
		while (it.hasNext ()) {
			v = it.next ();
			if (theX - theTolerance < v.x &&
				theX + theTolerance > v.x && 
				theY - theTolerance < v.y && 
				theY + theTolerance > v.y) {
				return v;
			}
		}
		return null;
	}
	
	public final V2f hasVector (V2f theVector, float theTolerance) {
		return hasVector (theVector.x, theVector.y, theTolerance);
	}
	
	public final V2fList add (float theX, float theY) {
		add (new V2f (theX, theY));
		return this;
	}
	
	public final V2fList add (V2fList theList) {
		Iterator<V2f> it = theList.iterator ();
		while (it.hasNext ()) {
			add (it.next ());
		}
		return this;
	}
	
	public final V2fList addCopy (V2f theVector) {
		add (theVector.clone ());
		return this;
	}
	
	public final V2fList addCopy (V2fList theList) {
		Iterator<V2f> it = theList.iterator ();
		while (it.hasNext ()) {
			add (it.next ().clone ());
		}
		return this;
	}
	
	public final V2f max (V2f theAxes) {
		V2f v = null;
		for (V2f o : this) {
			if (v == null) {
				v = o;
			}else{
				if (theAxes == V2f.X) {
					if (o.x > v.x) {
						v = o;
					}
				}else if (theAxes == V2f.Y) {
					if (o.y > v.y) {
						v = o;
					}
				}
			}
		}
		return v;
	}
	
	public final V2f min (V2f theAxes) {
		V2f v = null;
		for (V2f o : this) {
			if (v == null) {
				v = o;
			}else{
				if (theAxes == V2f.X) {
					if (o.x < v.x) {
						v = o;
					}
				}else if (theAxes == V2f.Y) {
					if (o.y < v.y) {
						v = o;
					}
				}
			}
		}
		return v;
	}
	
	public final V2fList move (float theX, float theY) {
		Iterator<V2f> it = iterator ();
		while (it.hasNext ()) {
			it.next ().add (theX, theY);
		}
		return this;
	}
	
	public final V2fList move (V2f theVector) {
		return move (theVector.x, theVector.y);
	}
	
	public final V2f nearest (float theX, float theY) {
		Iterator<V2f> it = iterator ();
		V2f r	= null;
		V2f v	= null;
		float d = 0;
		
		while (it.hasNext ()) {
			v = it.next ();
			if (r == null || d > v.distance (theX, theY)) {
				r = v.clone ();
				d = v.distance (theX, theY);
			}
		}
		return r;
	}
	
	public final V2f nearest (V2f theVector) {
		return nearest (theVector.x, theVector.y);
	}
	
	public final V2f nearestInRange (float theX, float theY, int theStartIndex, int theEndIndex) {
		int r	= -1;
		float d = 0;
		
		for (int i=theStartIndex; i <= theEndIndex; i++) {
			if (r == -1 || d > get (i).distance (theX, theY)) {
				r = i;
				d = get (i).distance (theX, theY);
			}
		}
		return (r > -1) ? get (r) : null;
	}
	
	public final V2f nearestInRange (V2f theVector, int theStartIndex, int theEndIndex) {
		return nearestInRange (theVector.x, theVector.y, theStartIndex, theEndIndex);
	}
	
	public final V2f nearestInRange (float theX, float theY, int theStartIndex, int theEndIndex, float theMaxDistance) {
		int r		= -1;
		float d1	= 0;
		float d2	= 0;
		
		for (int i=theStartIndex; i <= theEndIndex; i++) {
			
			d2 = get (i).distance (theX, theY);
			if (d1 > d2 && d2 < theMaxDistance || 
				r == -1 && d2 < theMaxDistance) {
				
				r	= i;
				d1	= d2;
			}
		}
		return (r > - 1) ? get (r) : null;
	}
	
	public final V2f nearestInRange (V2f theVector, int theStartIndex, int theEndIndex, float theMaxDistance) {
		return nearestInRange (theVector.x, theVector.y, theStartIndex, theEndIndex, theMaxDistance);
	}
	
	public final boolean remove (float theX, float theY) {
		Iterator<V2f> it = iterator ();
		V2f v;
		while (it.hasNext ()) {
			v = it.next ();
			if (v.equals (theX, theY)) {
				return remove (v);
			}
		}
		return false;
	}
	
	public final float pathLength () {
		float l = 0;
		for (int i=1; i < size (); i++) {
			l += get (i-1).distance (get (i));
		}
		return l;
	}
}